package com.carbeauty.common.util;

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.Date;

/**
 * 日期时间工具类
 * 
 * 提供常用的日期时间操作方法:
 * - 日期格式化和解析
 * - 日期计算和比较
 * - 时间段计算
 * - 业务日期判断
 * 
 * @author CarBeauty Team
 */
public class DateUtils {
    
    // ==================== 常用日期格式 ====================
    
    public static final String DATE_FORMAT = "yyyy-MM-dd";
    public static final String TIME_FORMAT = "HH:mm:ss";
    public static final String DATETIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
    public static final String TIMESTAMP_FORMAT = "yyyyMMddHHmmss";
    public static final String MONTH_FORMAT = "yyyy-MM";
    public static final String YEAR_FORMAT = "yyyy";
    
    // ==================== 格式化器 ====================
    
    public static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern(DATE_FORMAT);
    public static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern(TIME_FORMAT);
    public static final DateTimeFormatter DATETIME_FORMATTER = DateTimeFormatter.ofPattern(DATETIME_FORMAT);
    public static final DateTimeFormatter TIMESTAMP_FORMATTER = DateTimeFormatter.ofPattern(TIMESTAMP_FORMAT);
    public static final DateTimeFormatter MONTH_FORMATTER = DateTimeFormatter.ofPattern(MONTH_FORMAT);
    public static final DateTimeFormatter YEAR_FORMATTER = DateTimeFormatter.ofPattern(YEAR_FORMAT);
    
    // ==================== 格式化方法 ====================
    
    /**
     * 格式化日期为字符串
     */
    public static String formatDate(LocalDate date) {
        return date != null ? date.format(DATE_FORMATTER) : null;
    }
    
    /**
     * 格式化时间为字符串
     */
    public static String formatTime(LocalTime time) {
        return time != null ? time.format(TIME_FORMATTER) : null;
    }
    
    /**
     * 格式化日期时间为字符串
     */
    public static String formatDateTime(LocalDateTime dateTime) {
        return dateTime != null ? dateTime.format(DATETIME_FORMATTER) : null;
    }
    
    /**
     * 格式化日期时间为时间戳字符串
     */
    public static String formatTimestamp(LocalDateTime dateTime) {
        return dateTime != null ? dateTime.format(TIMESTAMP_FORMATTER) : null;
    }
    
    /**
     * 自定义格式化日期时间
     */
    public static String format(LocalDateTime dateTime, String pattern) {
        return dateTime != null ? dateTime.format(DateTimeFormatter.ofPattern(pattern)) : null;
    }
    
    // ==================== 解析方法 ====================
    
    /**
     * 解析日期字符串
     */
    public static LocalDate parseDate(String dateStr) {
        return dateStr != null && !dateStr.trim().isEmpty() ? LocalDate.parse(dateStr, DATE_FORMATTER) : null;
    }
    
    /**
     * 解析时间字符串
     */
    public static LocalTime parseTime(String timeStr) {
        return timeStr != null && !timeStr.trim().isEmpty() ? LocalTime.parse(timeStr, TIME_FORMATTER) : null;
    }
    
    /**
     * 解析日期时间字符串
     */
    public static LocalDateTime parseDateTime(String dateTimeStr) {
        return dateTimeStr != null && !dateTimeStr.trim().isEmpty() ? LocalDateTime.parse(dateTimeStr, DATETIME_FORMATTER) : null;
    }
    
    /**
     * 自定义解析日期时间
     */
    public static LocalDateTime parse(String dateTimeStr, String pattern) {
        return dateTimeStr != null && !dateTimeStr.trim().isEmpty() ? 
            LocalDateTime.parse(dateTimeStr, DateTimeFormatter.ofPattern(pattern)) : null;
    }
    
    // ==================== 当前时间获取 ====================
    
    /**
     * 获取当前日期
     */
    public static LocalDate now() {
        return LocalDate.now();
    }
    
    /**
     * 获取当前时间
     */
    public static LocalTime nowTime() {
        return LocalTime.now();
    }
    
    /**
     * 获取当前日期时间
     */
    public static LocalDateTime nowDateTime() {
        return LocalDateTime.now();
    }
    
    /**
     * 获取当前日期字符串
     */
    public static String nowDateStr() {
        return formatDate(now());
    }
    
    /**
     * 获取当前日期时间字符串
     */
    public static String nowDateTimeStr() {
        return formatDateTime(nowDateTime());
    }
    
    /**
     * 获取当前时间戳字符串
     */
    public static String nowTimestampStr() {
        return formatTimestamp(nowDateTime());
    }
    
    // ==================== 日期计算 ====================
    
    /**
     * 日期加天数
     */
    public static LocalDate plusDays(LocalDate date, long days) {
        return date != null ? date.plusDays(days) : null;
    }
    
    /**
     * 日期减天数
     */
    public static LocalDate minusDays(LocalDate date, long days) {
        return date != null ? date.minusDays(days) : null;
    }
    
    /**
     * 日期时间加天数
     */
    public static LocalDateTime plusDays(LocalDateTime dateTime, long days) {
        return dateTime != null ? dateTime.plusDays(days) : null;
    }
    
    /**
     * 日期时间减天数
     */
    public static LocalDateTime minusDays(LocalDateTime dateTime, long days) {
        return dateTime != null ? dateTime.minusDays(days) : null;
    }
    
    /**
     * 日期时间加小时
     */
    public static LocalDateTime plusHours(LocalDateTime dateTime, long hours) {
        return dateTime != null ? dateTime.plusHours(hours) : null;
    }
    
    /**
     * 日期时间减小时
     */
    public static LocalDateTime minusHours(LocalDateTime dateTime, long hours) {
        return dateTime != null ? dateTime.minusHours(hours) : null;
    }
    
    // ==================== 时间段计算 ====================
    
    /**
     * 计算两个日期之间的天数
     */
    public static long daysBetween(LocalDate startDate, LocalDate endDate) {
        return startDate != null && endDate != null ? ChronoUnit.DAYS.between(startDate, endDate) : 0;
    }
    
    /**
     * 计算两个日期时间之间的小时数
     */
    public static long hoursBetween(LocalDateTime startDateTime, LocalDateTime endDateTime) {
        return startDateTime != null && endDateTime != null ? ChronoUnit.HOURS.between(startDateTime, endDateTime) : 0;
    }
    
    /**
     * 计算两个日期时间之间的分钟数
     */
    public static long minutesBetween(LocalDateTime startDateTime, LocalDateTime endDateTime) {
        return startDateTime != null && endDateTime != null ? ChronoUnit.MINUTES.between(startDateTime, endDateTime) : 0;
    }
    
    /**
     * 计算两个日期时间之间的秒数
     */
    public static long secondsBetween(LocalDateTime startDateTime, LocalDateTime endDateTime) {
        return startDateTime != null && endDateTime != null ? ChronoUnit.SECONDS.between(startDateTime, endDateTime) : 0;
    }
    
    // ==================== 业务日期判断 ====================
    
    /**
     * 判断是否为今天
     */
    public static boolean isToday(LocalDate date) {
        return date != null && date.equals(LocalDate.now());
    }
    
    /**
     * 判断是否为今天
     */
    public static boolean isToday(LocalDateTime dateTime) {
        return dateTime != null && dateTime.toLocalDate().equals(LocalDate.now());
    }
    
    /**
     * 判断是否为本月
     */
    public static boolean isThisMonth(LocalDate date) {
        if (date == null) return false;
        LocalDate now = LocalDate.now();
        return date.getYear() == now.getYear() && date.getMonth() == now.getMonth();
    }
    
    /**
     * 判断是否为本年
     */
    public static boolean isThisYear(LocalDate date) {
        return date != null && date.getYear() == LocalDate.now().getYear();
    }
    
    /**
     * 判断日期是否在指定范围内
     */
    public static boolean isBetween(LocalDate date, LocalDate startDate, LocalDate endDate) {
        if (date == null || startDate == null || endDate == null) return false;
        return !date.isBefore(startDate) && !date.isAfter(endDate);
    }
    
    /**
     * 判断是否过期
     */
    public static boolean isExpired(LocalDate expiryDate) {
        return expiryDate != null && expiryDate.isBefore(LocalDate.now());
    }
    
    /**
     * 判断是否即将过期（指定天数内）
     */
    public static boolean isNearExpiry(LocalDate expiryDate, int days) {
        if (expiryDate == null) return false;
        LocalDate warningDate = LocalDate.now().plusDays(days);
        return expiryDate.isBefore(warningDate) && !expiryDate.isBefore(LocalDate.now());
    }
    
    // ==================== 特殊日期获取 ====================
    
    /**
     * 获取月初日期
     */
    public static LocalDate getMonthStart(LocalDate date) {
        return date != null ? date.with(TemporalAdjusters.firstDayOfMonth()) : null;
    }
    
    /**
     * 获取月末日期
     */
    public static LocalDate getMonthEnd(LocalDate date) {
        return date != null ? date.with(TemporalAdjusters.lastDayOfMonth()) : null;
    }
    
    /**
     * 获取年初日期
     */
    public static LocalDate getYearStart(LocalDate date) {
        return date != null ? date.with(TemporalAdjusters.firstDayOfYear()) : null;
    }
    
    /**
     * 获取年末日期
     */
    public static LocalDate getYearEnd(LocalDate date) {
        return date != null ? date.with(TemporalAdjusters.lastDayOfYear()) : null;
    }
    
    /**
     * 获取本月第一天
     */
    public static LocalDate getThisMonthStart() {
        return getMonthStart(LocalDate.now());
    }
    
    /**
     * 获取本月最后一天
     */
    public static LocalDate getThisMonthEnd() {
        return getMonthEnd(LocalDate.now());
    }
    
    // ==================== Date转换 ====================
    
    /**
     * Date转LocalDateTime
     */
    public static LocalDateTime toLocalDateTime(Date date) {
        return date != null ? date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime() : null;
    }
    
    /**
     * LocalDateTime转Date
     */
    public static Date toDate(LocalDateTime dateTime) {
        return dateTime != null ? Date.from(dateTime.atZone(ZoneId.systemDefault()).toInstant()) : null;
    }
    
    /**
     * LocalDate转Date
     */
    public static Date toDate(LocalDate date) {
        return date != null ? Date.from(date.atStartOfDay(ZoneId.systemDefault()).toInstant()) : null;
    }
}
